﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using Model;

namespace DAL
{
    public abstract class AbstractDAL<T>
    {
        protected abstract string InsertCommand { get; }
        protected abstract string UpdateCommand { get; }
        protected abstract string DeleteCommand { get; }
        protected abstract string SelectCommand { get; }
        protected abstract string SelectAllCommand { get; }
        protected abstract DbParameter[] GetInsertParameter(T model);
        protected abstract DbParameter[] GetUpdateParameter(T model);
        protected abstract DbParameter[] GetDeleteParameter(T model);
        protected abstract DbParameter[] GetSeleteParameter(long id);
        protected abstract T GetModel(DbDataReader reader);
        protected abstract void SyncID(T model, object scalar);

        public void  Insert(T model)
        {
            DbCommand command = null;
            try
            {
                command = SqlHelper.GetCommand(InsertCommand);
                DbParameter[] parameters = GetInsertParameter(model);
                command.Parameters.AddRange(parameters);
                object obj = command.ExecuteScalar();
                SyncID(model, obj);
            }
            finally
            {
                SqlHelper.Close(command);
            }
        }

        public void Update(T model)
        {
            DbCommand command = null;
            try
            {
                command = SqlHelper.GetCommand(UpdateCommand);
                DbParameter[] parameters = GetUpdateParameter(model);
                command.Parameters.AddRange(parameters);
                command.ExecuteNonQuery();
            }
            finally
            {
                SqlHelper.Close(command);
            }
        }

        public void Delete(T model,DbTransaction trans=null)
        {
            DbCommand command = null;
            try
            {
                command = SqlHelper.GetCommand(DeleteCommand, trans);
                DbParameter[] parameters = GetDeleteParameter(model);
                command.Parameters.AddRange(parameters);
                command.ExecuteNonQuery();
            }
            finally
            {
                SqlHelper.Close(command);
            }
        }

        public T Select(long id)
        {
            DbCommand command = null;
            DbDataReader reader = null;
            try
            {
                command = SqlHelper.GetCommand(SelectCommand);
                DbParameter[] parameters = GetSeleteParameter(id);
                command.Parameters.AddRange(parameters);
                reader = command.ExecuteReader();
                T model = GetModel(reader);
                return model;
            }
            finally
            {
                SqlHelper.Close(command, reader);
            }
        }

        public List<T> SelectAll()
        {
            List<T> list = new List<T>();
            DbCommand command = null;
            DbDataReader reader = null;
            try
            {
                command = SqlHelper.GetCommand(SelectAllCommand);
                reader = command.ExecuteReader();
                while (reader.Read())
                {
                    list.Add(GetModel(reader));
                }
                return list;
            }
            finally
            {
                SqlHelper.Close(command, reader);
            }
        }
    }
}
